package com.gitee.qdbp.vmall.sales.biz.order.main.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.gitee.qdbp.able.beans.KeyString;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.system.model.IAccount;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeBean;
import com.gitee.qdbp.general.common.api.reusable.service.ISimpleTreeQueryer;
import com.gitee.qdbp.general.common.api.settings.service.ISystemDataDictQueryer;
import com.gitee.qdbp.general.common.enums.ConfigScene;
import com.gitee.qdbp.general.system.api.personnel.model.UserCoreBean;
import com.gitee.qdbp.general.system.api.personnel.service.IUserCoreQueryer;
import com.gitee.qdbp.general.system.error.UserErrorCode;
import com.gitee.qdbp.general.trade.api.order.main.model.OrderFormBean;
import com.gitee.qdbp.general.trade.api.order.main.model.OrderItemBase;
import com.gitee.qdbp.general.trade.api.order.main.model.OrderItemBean;
import com.gitee.qdbp.general.trade.api.order.main.service.IOrderMainExecutor;
import com.gitee.qdbp.general.trade.api.order.main.service.IOrderMainQueryer;
import com.gitee.qdbp.general.trade.api.order.manage.model.OrderPaymentBean;
import com.gitee.qdbp.general.trade.api.order.manage.model.OrderPaymentWhere;
import com.gitee.qdbp.general.trade.api.order.manage.service.IOrderPaymentQueryer;
import com.gitee.qdbp.general.trade.enums.OrderState;
import com.gitee.qdbp.general.trade.enums.OrderType;
import com.gitee.qdbp.general.trade.enums.PayState;
import com.gitee.qdbp.tools.codec.CodeTools;
import com.gitee.qdbp.tools.specialized.KeywordHandler;
import com.gitee.qdbp.tools.utils.VerifyTools;
import com.gitee.qdbp.vmall.sales.api.goods.main.model.GoodsVersionBean;
import com.gitee.qdbp.vmall.sales.api.goods.main.model.GoodsVersionWhere;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeBean;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeUpdate;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeWhere;
import com.gitee.qdbp.vmall.sales.api.goods.manage.service.IInventoryRealtimeQueryer;
import com.gitee.qdbp.vmall.sales.api.order.main.model.CarrierBean;
import com.gitee.qdbp.vmall.sales.api.order.main.model.CreateGoodsOrderItem;
import com.gitee.qdbp.vmall.sales.api.order.main.model.CreateGoodsOrderParams;
import com.gitee.qdbp.vmall.sales.api.order.main.model.OrderReceiverBase;
import com.gitee.qdbp.vmall.sales.api.order.main.model.OrderReceiverBean;
import com.gitee.qdbp.vmall.sales.api.order.main.model.OrderReceiverUpdate;
import com.gitee.qdbp.vmall.sales.api.order.main.model.OrderReceiverWhere;
import com.gitee.qdbp.vmall.sales.api.order.main.service.IGoodsOrderExecutor;
import com.gitee.qdbp.vmall.sales.api.order.manage.model.OrderDeliveryBean;
import com.gitee.qdbp.vmall.sales.api.specific.model.SkuInstance;
import com.gitee.qdbp.vmall.sales.biz.goods.main.basic.GoodsVersionBasic;
import com.gitee.qdbp.vmall.sales.biz.goods.manage.basic.InventoryRealtimeBasic;
import com.gitee.qdbp.vmall.sales.biz.order.main.basic.OrderReceiverBasic;
import com.gitee.qdbp.vmall.sales.biz.order.manage.basic.OrderDeliveryBasic;
import com.gitee.qdbp.vmall.sales.enums.MallScene;
import com.gitee.qdbp.vmall.sales.error.MallErrorCode;

/**
 * 商品订单业务接口业务实现类
 *
 * @author zhaohuihua
 * @version 180625
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public class GoodsOrderExecutor implements IGoodsOrderExecutor {

    private static Logger log = LoggerFactory.getLogger(GoodsOrderExecutor.class);
    @Autowired
    private ISystemDataDictQueryer dataDictQueryer;
    @Autowired
    private ISimpleTreeQueryer simpleTreeQueryer;
    @Autowired
    private IUserCoreQueryer userCoreQueryer;
    @Autowired
    private GoodsVersionBasic goodsVersionBasic;
    @Autowired
    private OrderReceiverBasic orderReceiverBasic;
    @Autowired
    private OrderDeliveryBasic orderDeliveryBasic;
    @Autowired
    private IOrderMainQueryer orderMainQueryer;
    @Autowired
    private IOrderMainExecutor orderMainExecutor;
    @Autowired
    private IOrderPaymentQueryer orderPaymentQueryer;
    @Autowired
    private InventoryRealtimeBasic inventoryRealtimeBasic;
    @Autowired
    private IInventoryRealtimeQueryer inventoryRealtimeQueryer;

    @Override
    // 这里不需要事务, 都是查询和检查逻辑, 最后调事务方法创建订单ordreMainExecutor.create()
    @Transactional(propagation = Propagation.SUPPORTS)
    public String create(String userId, CreateGoodsOrderParams params, OrderReceiverBase receiver, IAccount operator)
            throws ServiceException {

        Date now = new Date();
        String msg = "Failed to create goods order. ";
        if (VerifyTools.isBlank(userId)) {
            log.error(msg + "params is null: UserId");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(params)) {
            log.error(msg + "params is null: CreateGoodsOrderParams");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(receiver)) {
            log.error(msg + "params is null: OrderReceiver");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(params.getItems())) {
            log.error(msg + "params is null: OrderItems");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 检查用户是否存在
        UserCoreBean user = userCoreQueryer.find(userId);
        if (user == null) {
            log.error(msg + "user[{}] not found.", userId);
            throw new ServiceException(UserErrorCode.USER_NOT_EXIST);
        }

        { // 检查当前用户是否存在支付中的付款单
            OrderPaymentWhere where = new OrderPaymentWhere();
            where.setUserId(userId);
            where.setOrderType(OrderType.GOODS);
            where.setPayState(PayState.PAYING);

            PageList<OrderPaymentBean> orders = orderPaymentQueryer.list(where, OrderPaging.COUNT);
            if (orders != null && orders.getTotal() > 0) {
                log.error(msg + "user[{}] current has order in payment, so can't create a new order.", userId);
                throw new ServiceException(MallErrorCode.ORDER_IN_PAYING_FOR_USER);
            }
        }

        Set<String> vids = new HashSet<>();
        PageList<GoodsVersionBean> goodses;
        { // 查询商品信息
            for (CreateGoodsOrderItem item : params.getItems()) {
                // 校验参数
                if (VerifyTools.isNotBlank(item.getGoodsVid())) {
                    vids.add(item.getGoodsVid());
                } else {
                    log.error(msg + "params is null: GoodsVid");
                    throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
                }
            }
            GoodsVersionWhere where = new GoodsVersionWhere();
            where.setVids(new ArrayList<>(vids));
            goodses = goodsVersionBasic.list(where, OrderPaging.NONE);
            if (VerifyTools.isBlank(goodses)) {
                log.error(msg + "params is null: OrderGoodses");
                throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
            }
        }
        // 检查商品及单品参数
        int codeLength = ISimpleTreeQueryer.CATEGORY_CODE_LENGTH;
        Set<String> skuIds = new HashSet<String>();
        Set<String> brandCodes = new HashSet<String>();
        for (CreateGoodsOrderItem item : params.getItems()) {
            String goodsVid = item.getGoodsVid();
            GoodsVersionBean goods = null;
            for (GoodsVersionBean bean : goodses) {
                if (goodsVid.equals(bean.getVid())) {
                    goods = bean;
                    break;
                }
            }
            if (goods == null) {
                log.error(msg + "Goods not found, GoodsVid={}", goodsVid);
                throw new ServiceException(ResultCode.PARAMETER_VALUE_ERROR);
            }
            if (VerifyTools.isNotBlank(goods.getBrandCode())) {
                brandCodes.addAll(CodeTools.split(goods.getBrandCode(), codeLength, true));
            }
            List<SkuInstance> skuData = goods.getSkuInstanceData();
            if (VerifyTools.isBlank(skuData)) {
                skuIds.add(goods.getUid()); // 单一商品的SkuId=GoodsUid
            } else {
                if (VerifyTools.isBlank(item.getSkuId())) { // 复合商品必须指定一个单品
                    log.error(msg + "SkuId is null, GoodsVid={}", goods.getVid());
                    throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
                } else {
                    String skuId = null;
                    for (SkuInstance sku : skuData) {
                        if (item.getSkuId().equals(sku.getId())) {
                            skuId = sku.getId();
                            break;
                        }
                    }
                    if (skuId == null) {
                        log.error(msg + "SkuId[{}] not found, GoodsVid={}", item.getSkuId(), goods.getVid());
                        throw new ServiceException(ResultCode.PARAMETER_VALUE_ERROR);
                    }
                }
            }
        }

        // 查询库存
        List<InventoryRealtimeBean> inventories = inventoryRealtimeQueryer.listBySkuId(new ArrayList<>(skuIds));

        List<OrderItemBase> orderItems = new ArrayList<>();
        KeywordHandler keywords = KeywordHandler.newInstance();
        for (CreateGoodsOrderItem item : params.getItems()) {
            String goodsVid = item.getGoodsVid();
            GoodsVersionBean goods = null;
            for (GoodsVersionBean bean : goodses) {
                if (goodsVid.equals(bean.getVid())) {
                    goods = bean;
                    break;
                }
            }

            OrderItemBase instance = new OrderItemBase();
            instance.setGoodsUid(goods.getUid()); // 商品唯一ID
            instance.setGoodsVid(goods.getVid()); // 商品版本ID
            instance.setBrandCode(goods.getBrandCode()); // 品牌ID
            instance.setModelNumber(goods.getModelNumber()); // 型号
            instance.setCategoryCode(goods.getCategoryCode()); // 商品分类编号
            instance.setGoodsName(goods.getName()); // 商品名称
            instance.setGoodsTitle(goods.getTitle()); // 商品标题
            instance.setGoodsUnit(goods.getUnit()); // 商品单位(个/件/台/袋等)
            instance.setQuantity(item.getQuantity()); // 购买数量
            instance.setDiscountAmount(item.getDiscountAmount()); // 折扣金额
            // instance.setGoodsAmount(null); // 商品金额=商品价格*数量-折扣(自动计算)

            keywords.addSegment(goods.getQueryKeywords());

            String skuId;
            List<SkuInstance> skuData = goods.getSkuInstanceData();
            if (VerifyTools.isBlank(skuData)) { // 单一商品
                instance.setSkuId(skuId = goods.getUid()); // 单品ID
                instance.setGoodsPrice(goods.getPriceValue()); // 商品价格
                instance.setSpecificText(null); // 规格描述
                instance.setPreviewImage(goods.getImageInfo(true).getPreview()); // 预览图片
            } else { // 复合商品
                skuId = item.getSkuId();
                SkuInstance sku = null;
                for (SkuInstance temp : skuData) {
                    if (skuId.equals(temp.getId())) {
                        sku = temp;
                        break;
                    }
                }
                instance.setSkuId(skuId); // 单品ID
                instance.setGoodsPrice(sku.getPriceValue()); // 商品价格
                instance.setSpecificText(sku.getSpecificText()); // 规格描述
                instance.setPreviewImage(sku.getImageInfo(true).getPreview()); // 预览图片
            }
            // 检查库存(只检查不锁定, 到支付跳转时才锁库存)
            InventoryRealtimeBean inventory = null;
            for (InventoryRealtimeBean temp : inventories) {
                if (skuId.equals(temp.getId())) {
                    inventory = temp;
                    break;
                }
            }
            if (inventory == null || inventory.getStockQuantity() < item.getQuantity()) {
                log.error(msg + "insufficient inventory, GoodsVid={}, SkuId={}", skuId, goodsVid);
                throw new ServiceException(MallErrorCode.GOODS_INSUFFICIENT_INVENTORY);
            }
        }

        // 获取品牌名称作为查询关键字
        if (VerifyTools.isNotBlank(brandCodes)) {
            String brandScene = MallScene.GOODS_BRAND.name();
            List<SimpleTreeBean> brands = simpleTreeQueryer.list(brandScene, new ArrayList<>(brandCodes), true);
            for (SimpleTreeBean brand : brands) {
                keywords.addPlain(brand.getNodeText());
            }
        }

        OrderFormBean orderForm = new OrderFormBean();
        // orderForm.setId(null); // 主键
        orderForm.setTenantCode(params.getTenantCode()); // 商家租户编号
        orderForm.setOrderType(OrderType.GOODS); // 订单类型(0.捐款订单|1.商品订单)
        // orderForm.setDataId(null); // 关联业务ID
        // orderForm.setOrderContent(null); // 订单内容
        orderForm.setUserId(userId); // 用户ID
        orderForm.setTotalAmount(null); // 总金额=商品金额-折扣+运费
        orderForm.setGoodsAmount(null); // 商品金额
        orderForm.setDiscountAmount(params.getDiscountAmount()); // 折扣金额
        orderForm.setFreightAmount(params.getFreightAmount()); // 运费金额
        // orderForm.setPaidAmount(null); // 已支付金额
        // orderForm.setTotalQuantity(null); // 商品总件数
        // orderForm.setDeliverQuantity(null); // 已发货件数
        orderForm.setCreateTime(now); // 创建时间
        // orderForm.setExpireTime(null); // 过期时间
        // orderForm.setOrderState(null); // 订单状态(0.待支付|1.已支付|2.已交付|3.已完成|4.已取消|5.已过期)
        orderForm.setOptions(params.getOptions()); // 选项
        orderForm.setQueryKeywords(keywords.toString()); // 查询关键字

        // 创建订单
        String orderId = orderMainExecutor.create(orderForm, orderItems, operator);

        // 保存收货地址
        OrderReceiverBean receiverBean = receiver.to(OrderReceiverBean.class);
        receiverBean.setId(null); // 主键
        receiverBean.setTenantCode(params.getTenantCode()); // 商家租户编号
        receiverBean.setOrderId(orderId); // 订单ID
        receiverBean.setSortIndex(0); // 排序号(0为当前有效记录)
        receiverBean.setCreateTime(now); // 创建时间
        // receiverBean.setOptions(null); // 选项
        orderReceiverBasic.create(receiverBean);

        return orderId;
    }

    @Override
    public void updateReceiver(String orderId, OrderReceiverBase receiver, IAccount operator) throws ServiceException {
        String msg = "Failed to update receiver of goods order. ";
        if (VerifyTools.isBlank(orderId)) {
            log.error(msg + "params is null: orderId");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (receiver == null) {
            log.error(msg + "params is null: receiver");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(receiver.getReceiverAddress())) {
            log.error(msg + "params is null: ReceiverAddress");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 查询订单
        OrderFormBean older = orderMainQueryer.find(orderId);
        if (older == null) {
            log.error(msg + "OrderForm not found, orderId={}", orderId);
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }

        { // 将之前的收货地址更新为失效状态
            OrderReceiverUpdate ud = new OrderReceiverUpdate();
            ud.setSortIndexAdd(1);
            OrderReceiverWhere w = ud.getWhere(true);
            w.setOrderId(orderId); // 订单ID
            w.setTenantCode(older.getTenantCode());
            orderReceiverBasic.create(ud);
        }
        { // 保存新的收货地址
            OrderReceiverBean receiverBean = receiver.to(OrderReceiverBean.class);
            receiverBean.setId(null); // 主键
            receiverBean.setTenantCode(older.getTenantCode()); // 商家租户编号
            receiverBean.setOrderId(orderId); // 订单ID
            receiverBean.setSortIndex(0); // 排序号(0为当前有效记录)
            // receiverBean.setCreateTime(new Date()); // 创建时间
            // receiverBean.setOptions(null); // 选项
            orderReceiverBasic.create(receiverBean);
        }
    }

    @Override
    public void deliverByCarrier(String orderId, CarrierBean carrier, IAccount operator) throws ServiceException {
        String msg = "Failed to update receiver of goods order. ";

        if (VerifyTools.isBlank(orderId)) {
            log.error(msg + "params is null: orderId");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (carrier == null) {
            log.error(msg + "params is null: carrier");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(carrier.getCompanyId())) {
            log.error(msg + "params is null: CarrierCompanyId");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(carrier.getVoucherCode())) {
            log.error(msg + "params is null: CarrierVoucherCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 查询订单主表
        OrderFormBean orderForm = orderMainQueryer.find(orderId);
        if (orderForm == null) {
            log.error(msg + "OrderForm not found, orderId={}", orderId);
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }
        OrderState state = orderForm.getOrderState();
        if (state != OrderState.PAID) {
            log.error(msg + "record state error. orderId={}, state={}", orderId, state);
            throw new ServiceException(ResultCode.RECORD_STATE_ERROR);
        }

        // 查询订单明细
        List<OrderItemBean> orderItems = orderMainQueryer.listItems(orderId);

        OrderReceiverBean receiver;
        { // 查询收货地址
            OrderReceiverWhere where = new OrderReceiverWhere();
            where.setOrderId(orderId);
            where.setSortIndex(0);
            receiver = orderReceiverBasic.find(where);
            if (receiver == null) {
                log.error(msg + "OrderReceiver not found, orderId={}", orderId);
                throw new ServiceException(ResultCode.SERVER_INNER_ERROR);
            }
        }

        // 获取快递公司名称作为查询关键字
        KeyString carrierCompany = dataDictQueryer.findObjectValue(ConfigScene.manager, orderForm.getTenantCode(),
            MallScene.CARRIER_COMPANY.key(), carrier.getCompanyId(), KeyString.class);
        // 追加快递公司和快递单号作为查询关键字
        KeywordHandler keywords = KeywordHandler.newInstance();
        keywords.addPlain(orderForm.getQueryKeywords());
        keywords.addPlain(carrier.getVoucherCode());
        if (carrierCompany != null) {
            keywords.addPlain(carrierCompany.getValue());
        }
        // 更新订单状态
        orderMainExecutor.deliverByCarrier(orderId, orderForm.getTotalQuantity(), keywords.toString());

        if (VerifyTools.isNotBlank(orderItems)) { // 更新已售库存量(待发货库存量)
            for (OrderItemBean item : orderItems) {
                InventoryRealtimeUpdate ud = new InventoryRealtimeUpdate();
                ud.setSoldQuantityAdd(-item.getQuantity());
                InventoryRealtimeWhere where = ud.getWhere(true);
                where.setSkuId(item.getSkuId());
                inventoryRealtimeBasic.update(ud, true);
            }
        }

        { // 创建交付记录
            OrderDeliveryBean bean = new OrderDeliveryBean();
            bean.setTenantCode(orderForm.getTenantCode()); // 租户编号
            bean.setOrderId(orderId); // 订单ID
            bean.setDelivererId(operator.getId()); // 发货人ID(内部员工)
            bean.setReceiverName(receiver.getReceiverName()); // 收件人姓名
            bean.setReceiverGender(receiver.getReceiverGender()); // 收件人性别(0.未知|1.男|2.女)
            bean.setReceiverPhone(receiver.getReceiverPhone()); // 收件人手机号码
            bean.setReceiverAreaCode(receiver.getReceiverAreaCode()); // 收件人城市(关联行政区划表)
            bean.setReceiverAddress(receiver.getReceiverAddress()); // 收件人地址
            bean.setCarrierCompanyId(carrier.getCompanyId()); // 快递公司ID
            bean.setCarrierVoucherCode(carrier.getVoucherCode()); // 快递单号
            bean.setCarrierClerkName(carrier.getClerkName()); // 取件快递员姓名
            bean.setCarrierClerkPhone(carrier.getClerkPhone()); // 取件快递员电话
            orderDeliveryBasic.create(bean);
        }

        // TODO description add to ProcessingRecord
    }

}
